import json
import subprocess
import re
import time
import os  # 添加这一行导入os模块

class CropOperations:
    """视频裁切相关操作"""
    
    def __init__(self):
        """初始化裁切操作类"""
        self.ffprobe_path = ""  # 将在FFmpegProcessor中设置
    
    def get_video_info(self, input_file):
        """获取视频文件的信息
        
        Args:
            input_file: 输入视频文件路径
            
        Returns:
            dict: 包含视频信息的字典，如果失败则返回None
        """
        try:
            # 检查ffprobe路径是否有效
            if not self.ffprobe_path or not os.path.exists(self.ffprobe_path):
                if hasattr(self, 'log_message'):
                    self.log_message.emit(f"ffprobe路径无效: {self.ffprobe_path}")
                return None
            
            # 使用ffprobe获取视频信息
            cmd = [
                self.ffprobe_path,
                '-v', 'quiet',
                '-print_format', 'json',
                '-show_format',
                '-show_streams',
                input_file
            ]
            
            if hasattr(self, 'log_message'):
                self.log_message.emit(f"执行命令: {' '.join(cmd)}")
            
            result = subprocess.run(cmd, capture_output=True, text=True)
            
            if result.returncode != 0:
                if hasattr(self, 'log_message'):
                    self.log_message.emit(f"获取视频信息失败: {result.stderr}")
                return None
            
            info = json.loads(result.stdout)
            
            # 查找视频流
            video_stream = None
            for stream in info.get('streams', []):
                if stream.get('codec_type') == 'video':
                    video_stream = stream
                    break
            
            if not video_stream:
                if hasattr(self, 'log_message'):
                    self.log_message.emit("未找到视频流")
                return None
            
            # 提取视频信息
            width = int(video_stream.get('width', 0))
            height = int(video_stream.get('height', 0))
            duration = float(video_stream.get('duration', 0))
            
            # 检查视频是否有旋转标记
            rotation = 0
            for tag in video_stream.get('tags', {}).items():
                if tag[0].lower() in ['rotate', 'rotation']:
                    try:
                        rotation = int(tag[1])
                    except ValueError:
                        pass
            
            # 如果视频旋转了90或270度，交换宽高
            if rotation in [90, 270]:
                width, height = height, width
            
            video_info = {
                'width': width,
                'height': height,
                'duration': duration,
                'rotation': rotation
            }
            
            if hasattr(self, 'log_message'):
                self.log_message.emit(f"获取到视频信息: {video_info}")
            
            return video_info
        
        except Exception as e:
            if hasattr(self, 'log_message'):
                self.log_message.emit(f"获取视频信息时出错: {str(e)}")
            return None
    
    def crop_video(self, input_file, output_file, crop_params, use_hardware_accel=False, progress_callback=None):
        """裁切视频
        
        Args:
            input_file: 输入视频文件路径
            output_file: 输出视频文件路径
            crop_params: 裁切参数字典，包含 x, y, width, height，以及可选的 pad 相关参数
            use_hardware_accel: 是否使用硬件加速
            progress_callback: 进度回调函数
            
        Returns:
            bool: 是否成功
        """
        try:
            # 获取视频信息以计算总时长
            video_info = self.get_video_info(input_file)
            if not video_info:
                self.log_message.emit("无法获取视频信息")
                return False
            
            total_duration = video_info.get('duration', 0)
            
            # 记录裁切信息
            original_width = video_info.get('width', 0)
            original_height = video_info.get('height', 0)
            new_width = crop_params.get('width', 0)
            new_height = crop_params.get('height', 0)
            
            if original_width and original_height and new_width and new_height:
                original_ratio = original_width / original_height
                new_ratio = new_width / new_height
                self.log_message.emit(f"原始比例: {original_ratio:.3f} ({original_width}:{original_height})")
                self.log_message.emit(f"目标比例: {new_ratio:.3f} ({new_width}:{new_height})")
            
            # 构建裁切命令
            cmd = [self.ffmpeg_path, '-y']
            
            # 添加硬件加速选项
            if use_hardware_accel:
                cmd.extend(['-hwaccel', 'auto'])
            
            cmd.extend(['-i', input_file])
            
            # 添加滤镜
            if crop_params.get('pad', False):
                # 需要添加黑边
                pad_filter = (
                    f"pad={crop_params['width']}:{crop_params['target_height']}:"
                    f"0:{crop_params['pad_top']}:black"
                )
                cmd.extend(['-vf', pad_filter])
                self.log_message.emit(f"使用填充滤镜: {pad_filter}")
            else:
                # 普通裁切
                crop_filter = f"crop={crop_params['width']}:{crop_params['height']}:{crop_params['x']}:{crop_params['y']}"
                cmd.extend(['-vf', crop_filter])
                self.log_message.emit(f"使用裁切滤镜: {crop_filter}")
            
            # 保持原始编码设置
            cmd.extend(['-c:v', 'libx264', '-preset', 'medium', '-crf', '23'])
            
            # 保持音频不变
            cmd.extend(['-c:a', 'copy'])
            
            cmd.append(output_file)
            
            # 记录完整命令
            self.log_message.emit(f"执行命令: {' '.join(cmd)}")
            
            # 启动进程
            process = subprocess.Popen(
                cmd, 
                stdout=subprocess.PIPE, 
                stderr=subprocess.PIPE,
                universal_newlines=True
            )
            
            # 监控进度
            if progress_callback and total_duration > 0:
                pattern = re.compile(r"time=(\d+):(\d+):(\d+\.\d+)")
                
                while process.poll() is None:
                    line = process.stderr.readline()
                    if not line:
                        continue
                    
                    match = pattern.search(line)
                    if match:
                        hours, minutes, seconds = map(float, match.groups())
                        current_time = hours * 3600 + minutes * 60 + seconds
                        progress = min(int(current_time / total_duration * 100), 100)
                        progress_callback(progress)
                    
                    time.sleep(0.1)
            
            # 等待进程完成
            process.wait()
            
            # 确保进度条到达100%
            if progress_callback:
                progress_callback(100)
            
            return process.returncode == 0
        
        except Exception as e:
            self.log_message.emit(f"裁切视频时出错: {str(e)}")
            return False